﻿using System;
using System.Collections;
using Assist;
using Autodesk.Revit.DB;
using YArchitech.Revit;

namespace YArchitech.Plumbing.Model
{
	public class BeamModel
	{
		public BeamModel(Element ele, Document _doc, Transform t, YJKViewRange hyvr, double z)
		{
			this.beam = ele;
			this.doc = _doc;
			try
			{
				FamilyInstance familyInstance = ele as FamilyInstance;
                //ele.Id.ToString() == "1089054";
				this.faceOri = familyInstance.FacingOrientation;
				Line line = (familyInstance.Location as LocationCurve).Curve as Line;
				BoundingBoxXYZ boundingBoxXYZ = ele.get_BoundingBox(_doc.ActiveView);
				if (t != null)
				{
					z = t.Origin.Z + z;
					this.tFrom = t;
				}
				if (this.IsInCurFloorRect(boundingBoxXYZ.Max, boundingBoxXYZ.Min, z, hyvr) && line != null)
				{
					this.systemLine = Line.CreateBound(line.Tessellate()[0] - new XYZ(0.0, 0.0, line.Tessellate()[0].Z), line.Tessellate()[1] - new XYZ(0.0, 0.0, line.Tessellate()[1].Z));
					if (t != null)
					{
						this.systemLine = Line.CreateBound(line.Tessellate()[0] + t.Origin - new XYZ(0.0, 0.0, t.Origin.Z) - new XYZ(0.0, 0.0, line.Tessellate()[0].Z), line.Tessellate()[1] + t.Origin - new XYZ(0.0, 0.0, t.Origin.Z) - new XYZ(0.0, 0.0, line.Tessellate()[1].Z));
					}
					this.GetBeamSize(ref this.Width, ref this.Height);
					if (this.Width < 0.1)
					{
						this.Width = 1.6404199475065617;
					}
					if (this.Height < 0.1)
					{
						this.Height = 1.6404199475065617;
					}
					this.IsParallel = false;
					if (Math.Abs(line.Tessellate()[0].Z - line.Tessellate()[1].Z) < 0.1)
					{
						this.IsParallel = true;
						this.GetElevation(familyInstance, t);
					}
				}
			}
			catch
			{
				this.systemLine = null;
			}
		}

		private void GetElevation(FamilyInstance fi, Transform t)
		{
			Line line = (fi.Location as LocationCurve).Curve as Line;
			this.Elevation = ((line.Tessellate()[0].Z < line.Tessellate()[1].Z) ? line.Tessellate()[0].Z : line.Tessellate()[1].Z);
			Parameter parameter = fi.GetParameter(BuiltInParameter.Z_OFFSET_VALUE);
			if (parameter != null)
			{
				this.Elevation += parameter.AsDouble();
			}
			if (t != null)
			{
				this.Elevation += t.Origin.Z;
			}
			Parameter parameter2 = fi.GetParameter(BuiltInParameter.Z_JUSTIFICATION);
			if (parameter2 != null)
			{
				if (parameter2.AsInteger() == 0)
				{
					this.Elevation -= this.Height / 2.0;
				}
				if (parameter2.AsInteger() == 3)
				{
					this.Elevation += this.Height / 2.0;
				}
			}
		}

		public bool IsInCurFloorRect(XYZ maxPoint, XYZ minPoint, double z, YJKViewRange floorRange)
		{
			if (floorRange.floorM != YJKViewRange.FloorMark.MidFloor && floorRange.floorM == YJKViewRange.FloorMark.TopFloor)
			{
				return false;
			}
			if (floorRange.floorM == YJKViewRange.FloorMark.MidFloor)
			{
				double num = z + floorRange.height;
				if (maxPoint.Z > z && maxPoint.Z > num && minPoint.Z > z && minPoint.Z > num)
				{
					return false;
				}
				if (maxPoint.Z < z && maxPoint.Z < num && minPoint.Z < z && minPoint.Z < num)
				{
					return false;
				}
			}
			return floorRange.floorM != YJKViewRange.FloorMark.TopFloor || maxPoint.Z >= z || minPoint.Z >= z;
		}

		public void GetBeamSize(ref double dWidth, ref double dHeight)
		{
			FamilyInstance familyInstance = this.beam as FamilyInstance;
			Line curve = (familyInstance.Location as LocationCurve).Curve as Line;
			XYZ hyendPoint = curve.GetEndPoint(0);
			XYZ hyendPoint2 = curve.GetEndPoint(1);
			XYZ vec = (hyendPoint2 - hyendPoint).Normalize();
			foreach (object obj in BeamModel.GetBeamFaces(familyInstance, this.doc.ActiveView))
			{
				PlanarFace planarFace = ((Face)obj) as PlanarFace;
				if (!(null == planarFace) && vec.IsParallelTo(planarFace.FaceNormal()))
				{
					EdgeArrayArray edgeLoops = planarFace.EdgeLoops;
					if (edgeLoops.Size == 1)
					{
                        EdgeArray edgeArray = edgeLoops.get_Item(0);
						if (edgeArray.Size == 4)
						{
							IEnumerator enumerator2 = edgeArray.GetEnumerator();
							{
								while (enumerator2.MoveNext())
								{
									object obj2 = enumerator2.Current;
									Line line = ((Edge)obj2).AsCurve() as Line;
									if (!(line == null))
									{
										hyendPoint = line.GetEndPoint(0);
										hyendPoint2 = line.GetEndPoint(1);
										double val = hyendPoint.DistanceTo(hyendPoint2);
										if (Math.Abs(hyendPoint.X - hyendPoint2.X) < 0.0001 && Math.Abs(hyendPoint.Y - hyendPoint2.Y) < 0.0001)
										{
											dHeight = Math.Max(dHeight, val);
										}
										if (Math.Abs(hyendPoint.Z - hyendPoint2.Z) < 0.0001)
										{
											dWidth = Math.Max(dWidth, val);
										}
									}
								}
								break;
							}
						}
					}
				}
			}
		}

		private static FaceArray GetBeamFaces(FamilyInstance beam, View view)
		{
			FaceArray faceArray = new FaceArray();
			Options options = new Options();
			options.View = view;
			foreach (GeometryObject geometryObject in RevitVersionFuncs.GetGeometryObjectArray(beam.Symbol.get_Geometry(options)))
			{
				if (geometryObject is Solid)
				{
					foreach (object obj in (geometryObject as Solid).Faces)
					{
						Face face = (Face)obj;
						faceArray.Append(face);
					}
				}
			}
			return faceArray;
		}

		public Element beam;

		public Line systemLine;

		private Document doc;

		public Transform tFrom;

		public double Elevation;

		public double Width;

		public double Height;

		public XYZ faceOri = XYZ.Zero;

		public bool IsParallel;
	}
}
